package top.yamhk.agent.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.system.SystemUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
import top.yamhk.agent.config.WechatApp;
import top.yamhk.agent.entity.dto.Felicity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 工具类
 *
 * @author 庆 HongKong
 * @date 2020/9/19 13:14
 */
@Slf4j
public class XcodeUtils {

    /**
     * 线程池名字
     */
    private static final ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNamePrefix("mt-{1}-{2}-").build();
    /**
     * 构建线程池
     * ArrayBlockingQueue和PriorityBlockingQueue使用较少，一般使用LinkedBlockingQueue和Synchronous。线程池的排序策略与BlockingQueue有关。
     */
    private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(55, 250, 555L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
    public static String replace4server = "{1}";
    public static String replace4client = "{2}";
    public static String impl4server = "bio";
    public static String impl4client = "exec";

    /**
     * 私有构造方法
     */
    private XcodeUtils() {
    }

    /**
     * 获取实例
     *
     * @return XcodeUtils
     */
    public static XcodeUtils newInstance() {
        return new XcodeUtils();
    }

    /**
     * 构建线程池
     *
     * @return ThreadPoolExecutor
     */
    public static ThreadPoolExecutor getDefaultExecutor() {
        return threadPoolExecutor;
    }

    /**
     * 休眠几秒
     *
     * @param second second
     */
    public static void sleepSecondThread(long second) {
        try {
            if (second < 100) {
                Thread.sleep(second * 1000);
            } else {
                Thread.sleep(second);
            }
        } catch (Exception e) {
            log.error("休眠异常:{}", e.getMessage());
        }
    }

    public static String getCustomerClassPath() {
        String absolutePath = new File("/root/hk/trans/20221201_00_00_00_1").getAbsolutePath();
        String filePath = absolutePath + File.separator;
        //class目录不存在则创建
        File file = new File(filePath);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            log.warn("File does not exist, file creation result:{}", mkdirs);
        }
        //如果是windows打开文件夹
        if (SystemUtil.getOsInfo().isWindows()) {
            try {
                Runtime.getRuntime().exec("explorer " + filePath);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return filePath;
    }

    public static void threadName(String localServer, String threadName) {
        localServer = StringUtils.isEmpty(localServer) ? XcodeUtils.impl4server : localServer;
        threadName = StringUtils.isEmpty(threadName) ? XcodeUtils.impl4client : threadName;
        String currentThreadName = Thread.currentThread().getName().replace(XcodeUtils.replace4server, localServer).replace(XcodeUtils.replace4client, threadName);
        Thread.currentThread().setName(currentThreadName);
    }

    public static List<File> dirScanFilesIntoList(File dirsPath, boolean deep, List<File> javaFileList) {
        //4655-StackOverflowError
        if (!dirsPath.exists()) {
            log.error("文件不存在");
            return Collections.emptyList();
        }
        if (dirsPath.isDirectory()) {
            File[] array = dirsPath.listFiles();
            if (array == null) {
                return Collections.emptyList();
            }
            List<File> dirs = Arrays.stream(array).map(e -> new File(e.getAbsolutePath())).collect(Collectors.toList());
            dirs.forEach(e -> {
                if (e.isDirectory()) {
                    if (deep) {
                        dirScanFilesIntoList(e, true, javaFileList);
                    }
                } else {
                    javaFileList.add(e);
                }
            });
        } else {
            javaFileList.add(dirsPath);
        }
        return javaFileList;
    }

    public static void unzipTranslateI(String fileName) {
        String fileNameStartAt = fileName.substring(0, 1);
        if (fileNameStartAt.compareTo("0") < 0 || fileNameStartAt.compareTo("9") > 0) {
            log.info("no need unzip-{}", fileNameStartAt);
            return;
        }
        String dateTimeStr = fileName.substring(0, 14);
        boolean before = false;
        try {
            before = Dates.parseNumberDateTime(dateTimeStr).before(DateUtils.addMinutes(Dates.now(), -30));
        } catch (Exception e) {
            log.error("{}", e.getMessage());
        }
        if (before) {
            log.info("压缩文件过期,下载也无效-{}", fileNameStartAt);
            return;
        }
        //zipFile
        File zip = new File("/root/hk/trans/" + fileName);
        //un-zip
        ZipUtil.unzip(zip, new File("/demo"));
        //move-copy
        FileUtil.copy(new File("/demo"), new File(Felicity.workspace), true);
        //del
        FileUtil.del(new File("/demo"));
    }

    @SneakyThrows
    public static void doOpenUrlByClient(int i, String qrCodeUrl) {
        if (i < 1) {
            return;
        }
        if (SystemUtil.getOsInfo().isWindows()) {
            Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + qrCodeUrl);
        } else if (SystemUtil.getOsInfo().isMac()) {
            Runtime.getRuntime().exec("/usr/bin/open " + qrCodeUrl);
        } else if (SystemUtil.getOsInfo().isLinux()) {
            // Unix or Linux
            String[] browsers = {"firefox", "opera", "konqueror", "epiphany", "mozilla", "netscape"};
            String browser = null;
            for (int count = 0; count < browsers.length && browser == null; count++) {
                // 条件判断中使用了==0，因为=0表示“等于0”，即“存在”
                if (Runtime.getRuntime().exec(new String[]{"which", browsers[count]}).waitFor() == 0) {
                    browser = browsers[count];
                }
            }
            if (browser == null) {
                throw new Exception("Could not find web browser");
            } else {
                Runtime.getRuntime().exec(new String[]{browser, qrCodeUrl});
            }
        }
    }

    /**
     * convertMultipartFileToFile
     *
     * @param multipartFile multipartFile
     * @return File
     */
    @SneakyThrows
    public static File convertMultipartFileToFile(MultipartFile multipartFile) {
        //文件上传时的文件名
        String fileName = multipartFile.getOriginalFilename();
        File file = new File("/tmp/" + fileName);
        //multipartFile.transferTo(new File("/tmp/" + fileName));
        try (OutputStream out = new FileOutputStream(file)) {
            byte[] ss = multipartFile.getBytes();
            for (byte s : ss) {
                out.write(s);
            }
        }
        // 验证写入的文件是否与上传的文件一致
        return new File(file.toURI());
    }

    public static List<String> partition(String string, int length) {
        int size = string.length() / length;
        size += string.length() % length == 0 ? 0 : 1;
        return getStrList(string, length, size);
    }

    private static List<String> getStrList(String string, int length, int size) {
        List<String> list = new ArrayList<>();
        for (int index = 0; index < size; index++) {
            String cs = substring(string, index * length, (index + 1) * length);
            list.add(cs);
        }
        return list;
    }

    private static String substring(String string, int s, int e) {
        if (s > string.length()) {
            return null;
        }
        if (e > string.length()) {
            return string.substring(s);
        } else {
            return string.substring(s, e);
        }
    }

    /**
     * 文件导出
     *
     * @param file file
     * @return ResponseEntity
     */
    public static ResponseEntity<FileSystemResource> exportFile(File file) {
        if (file == null) {
            log.error("{}", "文件不存在");
            return null;
        }
        log.warn("文件大小-{}-{}", file.length(), file.getTotalSpace());
        if (file.getTotalSpace() <= 1024) {
            log.error("{}", "文件大小异常");
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        //
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", "attachment; filename=" + file.getName());
        headers.add("Access-Control-Expose-Headers", "Content-Disposition");
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        headers.add("Last-Modified", new Date().toString());
        headers.add("ETag", String.valueOf(System.currentTimeMillis()));
        return ResponseEntity.ok()
                .headers(headers)
                .contentLength(file.length())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(new FileSystemResource(file));
    }

    public static Object fileToBase64(File file) {
        return FileUtil.readBytes(file);
    }

    public void testPathParam() throws IOException {
        log.info("打印路径参数:>>>");
        // 获取当前类的路径 涉及到jar包时，获取当前类的jar包路径
        System.out.println(new File(this.getClass().getResource("").getPath()));
        // 获取当前类的根路径
        System.out.println(new File(this.getClass().getResource("/").getPath()));
        // 获取类加载器的根路径
        System.out.println(this.getClass().getClassLoader().getResource(""));
        // 获取当前项目的绝对路径
        System.out.println(new File("").getCanonicalPath());
        // 获取当前工作目录
        System.out.println(System.getProperty("user.dir"));
        // 获取类路径，涉及jar包时，获取jar包的路径
        System.out.println(System.getProperty("java.class.path").split(";").length);
    }


    /**
     * 微信授权参数
     *
     * @return 请求授权的参数map
     */
    public static Map<String, Object> wxAuthMap() {
        WechatApp wechatApp = SpringUtil.getBean(WechatApp.class);
        log.info("====================================授权用户信息==============================");
        Map<String, Object> params = new HashMap<>(5);
        params.put("appid", wechatApp.getAppId());
        params.put("secret", wechatApp.getAppSecret());
        log.info("====================================授权请求参数：{}", params);
        return params;
    }
}
